﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

namespace WordFilterWCFService
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
                    ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class WordFilterWCFService : IWordFilterWCFService
    {
        public string WordFilter(string str)
        {
            string contents = str;
            if (str.Contains("<"))
            {
                contents = cleanUp(str).ToLower();
            }
            StopWords words = new StopWords(AppDomain.CurrentDomain.BaseDirectory + "/App_Data/StopWords.txt");
            foreach (string stopWord in words.WordList)
            {
                String pattern = String.Format(@"\b{0}\b", stopWord);
                contents = Regex.Replace(contents, pattern, "");
            }
            return contents;
        }

        /**
         * Removes newlines, everything in a script tag and html
         * markup in a string.
         */
        private string cleanUp(string str)
        {
            string contentsToReturn = "";
            contentsToReturn = removeNewlines(str);
            contentsToReturn = removeScriptTags(str);
            contentsToReturn = removeMarkupTags(str);
            return contentsToReturn;
        }

        private string removeMarkupTags(string str)
        {
            const string pattern = "([<][/]*\\w+[>])|([<](\\S+\\s+)\\S+[>])|[<][\\S+\\s+]+[/][>]|<[^>]+[/]*>";
            Regex regex = new Regex(pattern);
            return regex.Replace(str, "");
        }

        private string removeScriptTags(string str)
        {
            const string pattern = "([<][sS][cC][rR][iI][pP][tT].*[>].*[<][/][sS][cC][rR][iI][pP][tT][>])";
            Regex regex = new Regex(pattern, RegexOptions.Multiline);
            return regex.Replace(str, "");
        }

        private string removeNewlines(string str)
        {
            const string pattern = "[\n|\r|\r\n|\n\r]";
            Regex regex = new Regex(pattern);
            return regex.Replace(str, "");
        }

        class StopWords
        {
            private SortedSet<string> wordList = new SortedSet<string>();

            public SortedSet<string> WordList
            {
                get
                {
                    return new SortedSet<string>(wordList);
                }
            }

            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2200:RethrowToPreserveStackDetails")]
            public StopWords(string stopWordFilePath)
            {
                try
                {
                    using (StreamReader reader = new StreamReader(stopWordFilePath))
                    {
                        string[] contents = reader.ReadToEnd().Split();
                        foreach (string stopWord in contents)
                        {
                            if (stopWord.Length > 0)
                            {
                                wordList.Add(stopWord.ToLower());
                            }
                        }
                    }

                }
                catch (Exception e)
                {
                    throw e;
                }
            }

            public Boolean isStopWord(string word)
            {
                return wordList.Contains(word);
            }
        }
    }
}
